package com.one.pass.config;

import com.one.pass.service.ActiveMqService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
/*
TryAspect是一个切面类，用于处理带有@TryRun注解的方法。
在方法执行前，初始化相关资源；方法执行后，进行清理工作。
如果方法执行期间抛出异常，记录异常日志并调用ActiveMqService的tryRunMq方法进行处理
*/

@Aspect  // 标识这是一个切面类
@Component  // 表示这是一个Spring管理的组件
@Slf4j  // 使用lombok的Slf4j注解，自动生成一个名为log的日志对象
public class TryAspect {

    // 使用ThreadLocal来存储TryRunModel实例，保证线程安全
    public static ThreadLocal<TryRunModel> tryRunThreadLocal = new ThreadLocal<>();

    @Autowired  // 自动注入ActiveMqService
    private ActiveMqService activeMqService;

    // 定义一个切点，匹配使用了@TryRun注解的方法
    @Pointcut("@annotation(com.one.pass.config.TryRun)")
    public void web1() {
    }

    // 环绕通知，在方法执行前后进行处理
    @Around("web1()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object service = joinPoint.getTarget();  // 获取目标对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();  // 获取方法签名
        Method method = signature.getMethod();  // 获取目标方法
        Object[] objects = joinPoint.getArgs();  // 获取方法参数
        TryRun tryRun = method.getAnnotation(TryRun.class);  // 获取方法上的@TryRun注解
        try {
            return joinPoint.proceed();  // 执行目标方法
        } catch (Throwable e) {
            log.info("异常", e);  // 记录异常日志
            if (tryRunThreadLocal.get() == null) {
                // 调用ActiveMqService的tryRunMq方法处理异常
                activeMqService.tryRunMq(objects[0], method.getName(), service, tryRun.value());
            }
            throw e;  // 抛出异常
        } finally {
            tryRunThreadLocal.set(null);  // 清理ThreadLocal中的数据
        }
    }

}
